package com.lx.bbs.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
// 地址 当浏览器链接服务器所需要的地址
@ServerEndpoint("/talk/{id}")
public class TalkDo {

    // websocket 会为每个连接成功的客服端创建一个 talkdo 对象
    // 在线用户的容器
    private static Map<String, Session> onlines = new ConcurrentHashMap<>();

    // 链接成功执行的方法
    @OnOpen
    public void onOpen(Session session, @PathParam("id") String id) {
        session.getUserProperties().put("id", id);
        onlines.put(id, session);
        String json = buildMsg(id, "上线了", true);
        sendAllMessage(json);
    }

    @OnClose
    public void OnClose(Session session) {
        Object id = session.getUserProperties().get("id");
        onlines.remove(id);
        String json = buildMsg((String) id, "下线了", true);
        sendAllMessage(json);
    }

    @OnError
    public void OnError(Session session, Throwable throwable) {
        System.out.println("会话异常:" + throwable);
    }

    // 当接收到客户端发送的信息时触发的方法
    @OnMessage
    public void OnMessage(Session session, String message) throws IOException {
        Object id = session.getUserProperties().get("id");
        String json = buildMsg((String) id, message, false);
        sendAllMessage(json);
    }

    private void sendAllMessage(String message) {
        onlines.values().forEach(s->{
            try {
                s.getBasicRemote().sendText(message);
            } catch (IOException e) {
                throw new RuntimeException("发送消息失败",e);
            }
        });
    }

    ObjectMapper objectMapper = new ObjectMapper();

    public String buildMsg(String author, String content, boolean isOnlines){
        Msg msg = new Msg(author, content, null);
        if(isOnlines == true){
            // 一个包含 所有在线用户 id 的一个集合
            List<Object> onlinesId = onlines.values().
                    stream().
                    map(session -> session.getUserProperties().get("id")).
                    collect(Collectors.toList());
            msg.onlines = onlinesId;
        }
        try {
            return objectMapper.writeValueAsString(msg);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("转换消息错误", e);
        }
    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Msg{

    // 发送人
    String author;
    // 内容
    String content;
    // 下线人员列表
    List<Object> onlines;
}
